package com.wengen.mybatis.excutor;

import com.wengen.mybatis.config.Configuration;
import com.wengen.mybatis.config.MappedStatement;
import com.wengen.mybatis.reflection.ReflectionUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Auther: 朱稳根
 * @Date: 2018/8/27 22:38
 * @Description:
 */
public class DefaultExcutor implements Excutor {
    private Configuration conf;

    public DefaultExcutor(Configuration conf) {
        this.conf = conf;
    }

    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter) {
        List<E> ret = new ArrayList<E>();
        try {
            Class.forName(conf.getJdbcDriver());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            connection = DriverManager.getConnection(conf.getJdbcUrl(), conf.getJdbcUsername(), conf.getJdbcPassword());
            statement = connection.prepareStatement(ms.getSql());
            //参数转换
            parametrize(statement, parameter);
            rs = statement.executeQuery();
            //结果转换
            handlerResultSet(rs, ret, ms.getResultType());
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                rs.close();
                statement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    //查询结果集转换
    private <E> void handlerResultSet(ResultSet rs, List<E> ret, String resultType)  {
        Class<E> clazz = null;
        try {
            //通过反射获取类对象
            clazz = (Class<E>) Class.forName(resultType);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            while(rs.next()){
                //通过反射实例化对象
                Object entity = clazz.newInstance();
                //利用反射工具将resultSet的数据填充到entity里面去
                ReflectionUtil.setProToBeanFromResultSet(entity, rs);
                ret.add((E) entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //占位符参数转换，本例就一个参数
    private void parametrize(PreparedStatement statement, Object parameter) throws SQLException {
        if(parameter instanceof Integer) {
            statement.setInt(1, (int) parameter);
        }else if(parameter instanceof Long){
            statement.setLong(1, (long) parameter);
        } else if (parameter instanceof String) {
            statement.setString(1, String.valueOf(parameter));
        }
    }
}
